package com.qianclass.talklive.app.im;

import android.util.Log;

import com.google.gson.Gson;
import com.qianclass.talklive.app.bean.MemberInfo;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class DataParser extends Thread {
	private static final String      TAG         ="DataParser";
	private              DataPool    pool        = new DataPool();
	private              Queue<Byte> byte_stream =  new LinkedList<Byte>();
	PacketHead head = null;
	private byte[] packetHead = new byte[PacketHead.headLen];//包头
	byte[]   payload   = null;
	boolean  HeadMaked = false;
	Integer  nPayload  = 0;
	InPacket inPacket  = null;
	IMEgineEvent __event;
	IMEgine __engine = null;

	public  long last_msec = 0;

	private byte[]store_buffer=new byte[1024*10];
	private byte[]temp_buffer=new byte[1024*10];
	private int max_len=1024*10;
	private int store_len=0;
	private byte[] byteTemp = new byte[4];//临时包头的长度



	public DataParser(IMEgine egine, IMEgineEvent event)
	{
		__engine = egine;
		__event = event;
	}

	public void run()
	{
		while(true)
		{
			DataPool.DataBuffer obj = pool.pop_front();
			if(null == obj )
			{
				try
				{
					Thread.sleep(10);
				}
				catch (InterruptedException e)
				{
					e.printStackTrace();
				}
				continue;
			}
			//检查是否有充足的存储空间
			if ((max_len - store_len)<obj.GetLength()){
				store_len=0;
				//打印异常信息TODO：
			}

			//把新数据拼接到上次剩余的数据结尾

			System.arraycopy(obj.GetBuffer(), 0, store_buffer, store_len, obj.GetLength());

			store_len+=obj.GetLength();
			//如果够一个包头

			if(store_len<PacketHead.headLen){
				continue;
			}


			int nPacketLen = 0;
			int nPos = 0;
			int nRemain = 0;



			while (true)
			{
				//剩余字符个数
				nRemain = store_len -nPos;

				if (nRemain <= 0)
				{
					store_len= 0;
					break;
				}
//
				//如果剩余个数不够一个包

				//取出包体长度
				System.arraycopy(store_buffer, nPos, byteTemp, 0, 4);
				nPacketLen = Converter.byte2int(byteTemp);

				if (nPacketLen <= 0 || nPacketLen>max_len){
					//打印异常  TODO:
					try {
					throw new Exception("nPacketLen长度异常");
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					nPacketLen=0;
					break;


				}


				if (nRemain<nPacketLen){

					System.arraycopy(store_buffer, nPos, temp_buffer, 0, nRemain);
					System.arraycopy(temp_buffer, 0, store_buffer, 0, nRemain);
					store_len=nRemain;
					break;
				}



				// 构造包头
				System.arraycopy(store_buffer, nPos, packetHead, 0, PacketHead.headLen);
				head = new PacketHead( packetHead );
				// 从包头中得到包体长度
				nPayload = head.nPacketLen - PacketHead.headLen;

				if(nPayload < 0 || nPayload>max_len){
					//打印异常  TODO:
					System.out.print("nPayload长度"+nPayload);
					System.out.print("max_len长度"+max_len);
					try {
						throw new Exception("nPayload长度异常");
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					store_len=0;
					break;


				}

				payload = new byte[nPayload];

				System.arraycopy(store_buffer, nPos+PacketHead.headLen, payload, 0, nPayload);

				inPacket = new InPacket( payload, nPayload);//构造payload
				Packet packet = new Packet( head, inPacket);//构造完整包
				Deliver(packet);
				nPos += nPacketLen;
				if(nPacketLen>PacketHead.headLen){
					System.out.println("nPacketLen"+nPacketLen);
				}
			}





			/*for(Integer i = 0; i < obj.GetLength(); i++)
				byte_stream.add(obj.GetBuffer()[i]);
			if(!HeadMaked)
			{ // 如果包头还没有构造，则构造包头
				if(byte_stream.size() >= PacketHead.headLen )
				{
					for(Integer i = 0; i < PacketHead.headLen; i++ )
					{
						packetHead[i] = byte_stream.remove();
					}
					// 构造包头

					head = new PacketHead( packetHead );
					// 从包头中得到包体长度
					nPayload = head.nPacketLen - PacketHead.headLen;
					payload = new byte[nPayload];
					HeadMaked = true;
				}
			}
			if(HeadMaked)
			{
				if(byte_stream.size() >= nPayload )
				{
					for(Integer i = 0; i < nPayload; i++ )
					{
						payload[i] = byte_stream.remove();
					}
					inPacket = new InPacket( payload, nPayload);
					Packet packet = new Packet( head, inPacket);
					Deliver(packet);
					HeadMaked = false;
				}
			}	*/



		}
	}



	public void AddData(byte[] data, int nLen)
	{
		pool.push_back(data, nLen);
	}

	private void Deliver(Packet pak)
	{
		switch (pak.head.nPacketType)
		{
			case ConstantDefination.IM_COMMAND_ONREGISTER:
			{
				last_msec= System.currentTimeMillis();

				int errCode = pak.in.getValueByInt();
				int userId = pak.in.getValueByInt();
				int userAgencyId = pak.in.getValueByInt();
				String userAgencyName = pak.in.getValueByString();
				String userOrgName = pak.in.getValueByString();
				String account = userId + ":" + __engine.login_user_name + "@" + userOrgName + "." + userAgencyId;

				Log.e("OnRegister", account);

				//接口回调监听
				__event.OnRegister(errCode, userId, account);

				// 写日志
				String dump = "server: OnRegister(" + errCode + "," + userId + "," + userAgencyId + ","
						+ userAgencyName + "," + userOrgName + ")";
				__engine.log.WriteLine(dump);

				if (errCode == ConstantDefination.RESULT_SUCCESS) {
					//存储机构信息
					__engine.agency_manger.AddAgency(userAgencyId, userAgencyName);
					// 向服务器请求代理信息
					__engine.FetchAgInfo();
				}
			}
			break;

			case ConstantDefination.IM_COMMAND_FETCHAGINFO:
			{
				int errCode = pak.in.getValueByInt();
				int count = pak.in.getValueByInt();

				for(int i = 0; i < count; i++)
				{
					int agid = pak.in.getValueByInt();
					String agency_name = pak.in.getValueByString();

					if (errCode == ConstantDefination.RESULT_SUCCESS) {
						__engine.agency_manger.AddAgency(agid, agency_name);
					}
				}
			}
			break;

			case ConstantDefination.IM_COMMAND_ONUNREGISTER:
			{
				int errCode = pak.in.getValueByInt();

				__event.OnUnRegister(errCode);
				//写日志
				String dump = "server: OnUnRegister(" + errCode + ")";
				__engine.log.WriteLine(dump);

				if(errCode == ConstantDefination.RESULT_SUCCESS)
				{
					__engine.login_user_id = 0;
					__engine.login_user_name = null;
					__engine.login_user_type = 0;
					__engine.login_user_key = null;
				}
			}
			break;

			case ConstantDefination.IM_COMMAND_ONJOINGROUP:
			{
				int errCode = pak.in.getValueByInt();
				int groupId = pak.in.getValueByInt();
				int groupCount = pak.in.getValueByInt();
				int groupAgentId = pak.in.getValueByInt();
				String groupAgencyName = pak.in.getValueByString();
				String groupOrgName = pak.in.getValueByString();

				String groupCode = "g:" + groupId + "@" + groupOrgName + "." + groupAgencyName;

				MemberInfo memberInfo = new MemberInfo();
				List<MemberInfo.ListBean> memberList = new ArrayList<>();
				memberInfo.setResult("RESULT_SUCCESS");
				for (int i = 0; i < groupCount; i++) {
					int userId = pak.in.getValueByInt();
					int userType = pak.in.getValueByInt();
					String userName = pak.in.getValueByString();
					int agencyId = pak.in.getValueByInt();
					String agencyName = pak.in.getValueByString();
					String orgName = pak.in.getValueByString();

					String useraccount = userId + ":" + userName + "@" + orgName + "." + agencyName;

					MemberInfo.ListBean listBean = new MemberInfo.ListBean();
					listBean.setUserid(userId + "");
					listBean.setUsername(userName);
					listBean.setType(userType);
					listBean.setAccount(useraccount);
					memberList.add(listBean);
				}

				memberInfo.setList(memberList);

				String userList = new Gson().toJson(memberInfo);
				__event.OnJoinGroup(errCode, groupCode, userList);

				String dump = "server: OnJoinGroup(" + errCode + "," + groupCode + "," + userList + ")";
				__engine.log.WriteLine(dump);

				if (errCode == ConstantDefination.RESULT_SUCCESS) {
					__engine.agency_manger.AddAgency(groupAgentId, groupAgencyName);
					__engine.group_manager.AddGroup(groupId, groupCode);
				}
			}
			break;

			case ConstantDefination.IM_COMMAND_GROUPUSERLIST:
			{
				int errCode = pak.in.getValueByInt();
				int groupId = pak.in.getValueByInt();
				int groupCount = pak.in.getValueByInt();
				int groupAgentId = pak.in.getValueByInt();
				String groupAgencyName = pak.in.getValueByString();
				String groupOrgName = pak.in.getValueByString();

				String groupCode = "g:" + groupId + "@" + groupOrgName + "." + groupAgencyName;

				MemberInfo memberInfo = new MemberInfo();
				List<MemberInfo.ListBean> memberList = new ArrayList<>();
				memberInfo.setResult("RESULT_SUCCESS");
				for (int i = 0; i < groupCount; i++) {
					int userId = pak.in.getValueByInt();
					int userType = pak.in.getValueByInt();
					String userName = pak.in.getValueByString();
					int agencyId = pak.in.getValueByInt();
					String agencyName = pak.in.getValueByString();
					String orgName = pak.in.getValueByString();

					String useraccount = userId + ":" + userName + "@" + orgName + "." + agencyName;

					MemberInfo.ListBean listBean = new MemberInfo.ListBean();
					listBean.setUserid(userId + "");
					listBean.setUsername(userName);
					listBean.setType(userType);
					listBean.setAccount(useraccount);
					memberList.add(listBean);
				}

				memberInfo.setList(memberList);
				String userList = new Gson().toJson(memberInfo);

				__event.OnGroupUserList(errCode, groupCode, userList);

				String dump = "server: OnJoinGroup(" + errCode + "," + groupCode + "," + userList + ")";
				__engine.log.WriteLine(dump);

				if (errCode == ConstantDefination.RESULT_SUCCESS) {
					__engine.agency_manger.AddAgency(groupAgentId, groupAgencyName);
					__engine.group_manager.AddGroup(groupId, groupCode);
				}
			}
			break;

			case ConstantDefination.IM_COMMAND_ONLEAVEGROUP:
			{
				int errCode = pak.in.getValueByInt();
				int groupId = pak.in.getValueByInt();
				String agencyName = pak.in.getValueByString();
				String orgName = pak.in.getValueByString();
				String groupCode = "g:" + groupId + "@" + orgName + "." + agencyName;

				__event.OnLeaveGroup(errCode, groupCode);

				String dump = "server: OnLeaveGroup(" + errCode + "," + groupCode + ")";
				__engine.log.WriteLine(dump);

				if (errCode == ConstantDefination.RESULT_SUCCESS) {
					__engine.group_id = 0; // 当前用户加入的组id
					__engine.group_title = null; 	// 当前用户加入的组名称
				}
			}
			break;

			case ConstantDefination.IM_COMMAND_ONUSERJOINGROUP:
			{
				int errCode = pak.in.getValueByInt();
				int groupId = pak.in.getValueByInt();
				int userId = pak.in.getValueByInt();
				int userType = pak.in.getValueByInt();
				String userName = pak.in.getValueByString();
				int agencyId = pak.in.getValueByInt();
				String agencyName = pak.in.getValueByString();
				String orgName = pak.in.getValueByString();
				String userAccount = userId + ":" + userName + "@" + orgName + "." + agencyName;

				__event.OnUserJoinGroup(errCode, userAccount, userName, userType);
				// 写日志
				String dump = "server: OnUserJoineGroup(" + groupId + "," + userId + "," + userType + "," + userName + ")";
				__engine.log.WriteLine(dump);
			}
			break;

			case ConstantDefination.IM_COMMAND_ONUSERLEAVEGROUP:
			{
				int errCode = pak.in.getValueByInt();
				int groupId = pak.in.getValueByInt();
				int userId = pak.in.getValueByInt();
				int userType = pak.in.getValueByInt();
				String userName = pak.in.getValueByString();
				int agencyId = pak.in.getValueByInt();
				String agencyName = pak.in.getValueByString();
				String orgName = pak.in.getValueByString();
				short leaveType = pak.in.getValueByShort((short) 1);

				String userAccount = userId + ":" + userName + "@" + orgName + "." + agencyName;

				__event.OnUserLeaveGroup(errCode, userAccount, userName, userType, leaveType);
				String dump = "server: OnUserLeaveGroup(" + groupId + "," + userAccount + "," + userName + "," + userType + ")";
				__engine.log.WriteLine(dump);

			}
			break;

			case ConstantDefination.IM_COMMAND_MESSAGE:
			{
				String messageData = pak.in.getValue();
				__event.OnReceiveMessage(messageData);
				String dump = "server: IM_COMMAND_MESSAGE(" + messageData + ")";
				__engine.log.WriteLine(dump);
			}
			break;

			case ConstantDefination.IM_COMMAND_GMESSAGE:
			{
				String messageData  = pak.in.getValue();

				Log.e("gMessage", pak.head.nToid + "|||" +messageData);

				__event.OnReceiveGroupMessage(messageData);

				String dump = "server: IM_COMMAND_GMESSAGE(" + messageData + ")";
				__engine.log.WriteLine(dump);
			}
			break;

			case ConstantDefination.IM_COMMAND_ACK:
			{
				last_msec = System.currentTimeMillis();
			}
			break;

			case ConstantDefination.IM_COMMAND_SERVERNOTIFICATION:
			{
				int errCode = pak.in.getValueByInt();
				__event.OnServerNotification(errCode);
				String dump = "server: parse_OnServerNotification(" + errCode + ")";
				__engine.log.WriteLine(dump);
			}
			break;

			case ConstantDefination.IM_COMMAND_ONLOCKUSER:
			{
				int errCode = pak.in.getValueByInt();
				int userId = pak.in.getValueByInt();
				int lockType = pak.in.getValueByInt();

				Log.d("IM", "IM_COMMAND_ONLOCKUSER");
				__event.onLockUserAccount(errCode, userId, lockType);

				String dump = "server: OnLockUserAccount(" + userId + "," + lockType + ")";
				__engine.log.WriteLine(dump);
			}
			break;

			default:
				System.err.println("错误包类型");
				break;
		}
	}
}